//////////////////////////////////////////////////////////////////////////////////
//                                                                              //
//  This file is part of the buola project (https://code.google.com/p/buola/).  //
//                                                                              //
//  Copyright(c) 2007-2012 Xavi Gratal                                          //
//  gratal AT gmail DOT com                                                     //
//                                                                              //
//  Buola is free software: you can redistribute it and/or modify               //
//  it under the terms of the GNU General Public License as published by        //
//  the Free Software Foundation, either version 3 of the License, or           //
//  (at your option) any later version.                                         //
//                                                                              //
//  Buola is distributed in the hope that it will be useful,                    //
//  but WITHOUT ANY WARRANTY; without even the implied warranty of              //
//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the               //
//  GNU General Public License for more details.                                //
//                                                                              //
//  You should have received a copy of the GNU General Public License           //
//  along with buola.  If not, see <http://www.gnu.org/licenses/>.              //
//                                                                              //
//////////////////////////////////////////////////////////////////////////////////

#include <buola/tty/csimpleshell.h>
#include <buola/algorithm/split.h>

namespace buola { namespace tty {
    
CSimpleShell::CSimpleShell()
    :   mPrompt(L"> ")
{
    mLineReader.sCompleteW.Connect(&CSimpleShell::Complete,this,_1,_2,_3);
}

void CSimpleShell::SetPrompt(const std::wstring &pPrompt)
{
    mPrompt=pPrompt;
}

std::wstring CSimpleShell::GetPrompt()
{
    return mPrompt;
}

void CSimpleShell::Loop()
{
    mStop=false;
//    mLineReader.LoadHistory(io::get_home()/".bush_history");
    
    while(!mLineReader.IsEOF()&&!mStop)
    {
        try
        {
            mLineReader.SetPrompt(mPrompt);
            std::wstring lLine=mLineReader.ReadWLine();

            ProcessLine(utf8(lLine));

            if(!lLine.empty())
                mLineReader.AddToHistory(lLine);
        }
        catch(XInternal &pE)
        {
        }
    }
    
//    mLineReader.SaveHistory(io::get_home()/".bush_history");
}

void CSimpleShell::Stop()
{
    mStop=true;
}

void CSimpleShell::AddCommand(const std::string &pName,const TFunction &pFunction)
{
    std::unique_ptr<SCommand> lCmd(new SCommand);
    
    lCmd->mName=pName;
    lCmd->mFunction=pFunction;
    
    mCommands.Add(pName,std::move(lCmd));
}

void CSimpleShell::ProcessLine(const std::string &pLine)
{
    std::vector<std::string> lTokens;
    
    split(pLine,lTokens,fn::is_ascii_space(),nDeleteEmpty);
    
    if(lTokens.size()<1) return;
    
    std::vector<temp_ptr<SCommand>> lMatches;
    mCommands.FindAll(lTokens[0],lMatches);
    
    if(lMatches.size()==1)
    {
        try
        {
            lMatches[0]->mFunction(lTokens);
        }
        catch(std::exception &pE)
        {
            msg_error() << pE.what() << "\n";
        }
        catch(...)
        {
            msg_error() << "unknown error\n";
        }
    }
    else
    {
        msg_info() << "ambiguous command\n";
    }
}

bool CSimpleShell::Complete(const std::wstring &pLine,int pCursor,tty::CCompletion<std::wstring> &pComp)
{
    return false;
/*
    std::wstring lJoin=mAccumLine+pLine;
    
    CPartialMatch lMatch;
    mParser.ParsePartial(lJoin.begin(),lJoin.begin()+mAccumLine.length()+pCursor,lMatch);
    
    if(lMatch.mContext==COMP_NONE) return false;
    
    pComp.mB=lMatch.mWordB-lJoin.begin()-mAccumLine.size();
    pComp.mE=lMatch.mWordE-lJoin.begin()-mAccumLine.size();

    if(lMatch.mContext&COMP_SHELL)
    {
        if(CompleteShell(lMatch,pComp))
            return true;
    }
    if(lMatch.mContext&COMP_PYTHON_ANY)
    {
        CompletePython(lMatch,pComp);
    }
    
    return true;
*/
}

/*namespace tty*/ } /*namespace buola*/ }
